`timescale 1ns / 1ps

module zq_rom_loader
#(
    parameter WIDTH = 1280,
    parameter DEPTH = 768,
    parameter ROM_TYPE = "block",        // block or distributed
    parameter ROM_FILE = "L9_PW.mem",
    parameter ROM_LATENCY = 2
)
(
    input   clk,
    input   rst,

    input   o_rdy,
    output  o_vld,
    output  [WIDTH-1: 0]    o_data
);

localparam ADDR_WIDTH = $clog2(DEPTH);

wire [ADDR_WIDTH-1: 0] addr;
wire enable;

zq_counter #(
    .N  (DEPTH)
) inst_addr
(
    .clk    (clk),
    .rst    (rst),
    .clken  (enable),
    .last   (),
    .out    (addr)
);

zq_sprom_hs #(
    .ADDR_WIDTH ( ADDR_WIDTH  ),
    .DATA_WIDTH (      WIDTH  ),
    .DEPTH      ( DEPTH       ),
    .LATENCY    ( ROM_LATENCY ),
    .ROMTYPE    ( ROM_TYPE    ),
    .ROMFILE    ( ROM_FILE    )
)
inst_rom_hs (
    .clk                     ( clk      ),
    .rst                     ( rst      ),

    .read_rdy                ( enable   ),
    .read_vld                ( 1'b1     ),
    .addr                    ( addr     ),

    .out_rdy                 ( o_rdy    ),
    .out_vld                 ( o_vld    ),
    .dout                    ( o_data   )
);

endmodule


module zq_rom_advloader
#(
    parameter N_HEI = 4,
    parameter N_BLK = 16,
    parameter WIDTH = 1280,
    parameter DEPTH = 768,
    parameter ROM_TYPE = "block",
    parameter ROM_FILE = "L9_PW.mem",
    parameter ROM_LATENCY = 2
)
(
    input   clk,
    input   rst,

    input   o_rdy,
    output  o_vld,
    output  [WIDTH-1: 0]    o_data
);

localparam ADDR_WIDTH = $clog2(DEPTH);
localparam  ALO_WIDTH = $clog2(N_BLK);
localparam  AHI_WIDTH = ADDR_WIDTH - ALO_WIDTH;

wire [ADDR_WIDTH-1: 0] addr;
wire [ ALO_WIDTH-1: 0] lo;
wire [ AHI_WIDTH-1: 0] hi;
wire lo_last;
wire rp_last;
wire enable;

assign addr = N_BLK * hi + lo;

zq_counter #(
    .N  (N_BLK)
) inst_cnt_alo
(
    .clk    (clk),
    .rst    (rst),
    .clken  (enable),
    .last   (lo_last),
    .out    (lo)
);

zq_counter #(
    .N  (N_HEI)
) inst_cnt_rep
(
    .clk    (clk),
    .rst    (rst),
    .clken  (enable & lo_last),
    .last   (rp_last),
    .out    ()
);

zq_counter #(
    .N  (DEPTH / N_BLK)
) inst_cnt_ahi
(
    .clk    (clk),
    .rst    (rst),
    .clken  (enable & lo_last & rp_last),
    .last   (),
    .out    (hi)
);

zq_sprom_hs #(
    .ADDR_WIDTH ( ADDR_WIDTH  ),
    .DATA_WIDTH (      WIDTH  ),
    .DEPTH      ( DEPTH       ),
    .LATENCY    ( ROM_LATENCY ),
    .ROMTYPE    ( ROM_TYPE    ),
    .ROMFILE    ( ROM_FILE    )
)
inst_rom_hs (
    .clk                     ( clk      ),
    .rst                     ( rst      ),

    .read_rdy                ( enable   ),
    .read_vld                ( 1'b1     ),
    .addr                    ( addr     ),

    .out_rdy                 ( o_rdy    ),
    .out_vld                 ( o_vld    ),
    .dout                    ( o_data   )
);

endmodule

